package com.example.multithread.completablefuture;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.IntStream;

/**
 * @ClassName CompletableFutureDemo
 * @Description TODO
 * @Author leejiliang
 * @DateTime 2020/5/15 3:53 PM
 * @Version 1.0
 */
@Slf4j
public class CompletableFutureDemo {
	public static void main(String[] args) throws ExecutionException, InterruptedException {
		List<User> userList = List.of(
				User.builder().id(1L).name("a").age(18).gender(Gender.M).build(),
				User.builder().id(2L).name("b").age(20).gender(Gender.F).build(),
				User.builder().id(3L).name("c").age(22).gender(Gender.M).build(),
				User.builder().id(4L).name("d").age(28).gender(Gender.F).build(),
				User.builder().id(5L).name("e").age(31).gender(Gender.F).build());
		//多少个男性, 多少个女性, 年龄 25 以上有多少, 25 及一下有多少人.
		StopWatch stopWatch = new StopWatch();
		stopWatch.start("普通处理方式");
		log.info("普通方式: {}", normal(userList).toString());
		stopWatch.stop();
		stopWatch.start("Future+多线程处理方式");
		log.info("Future+多线程方式: {}", futureDemo(userList).toString());
		stopWatch.stop();
		log.info(stopWatch.prettyPrint());
	}

	static Map<String, Long> normal(List<User> userList) {
		long mCount = userList.stream().filter(i -> Gender.M.equals(i.getGender())).count();
		long fCount = userList.stream().filter(i -> Gender.F.equals(i.getGender())).count();
		long oldCount = userList.stream().filter(i -> i.getAge() > 25).count();
		long youngCount = userList.stream().filter(i -> i.getAge() <= 25).count();
		return Map.of(
				"mCount", mCount,
				"fCount", fCount,
				"oldCount", oldCount,
				"youngCount", youngCount);
	}

	static Map<String, Long> futureDemo(List<User> userList) throws ExecutionException, InterruptedException {
		ExecutorService executorService = Executors.newFixedThreadPool(4);
		Future<Long> mCount = executorService.submit(() -> userList.stream().filter(i -> Gender.M.equals(i.getGender())).count());
		Future<Long> fCount = executorService.submit(() -> userList.stream().filter(i -> Gender.F.equals(i.getGender())).count());
		Future<Long> oldCount = executorService.submit(() -> userList.stream().filter(i -> i.getAge() > 25).count());
		Future<Long> youngCount = executorService.submit(() -> userList.stream().filter(i -> i.getAge() <= 25).count());
		return Map.of(
				"mCount", mCount.get(),
				"fCount", fCount.get(),
				"oldCount", oldCount.get(),
				"youngCount", youngCount.get());
	}

	static Long getMcount(List<User> userList) {
		return userList.stream().filter(i -> Gender.M.equals(i.getGender())).count();
	}

	static Future<Long> getMcountAsync(List<User> userList) {
		ExecutorService executorService = Executors.newFixedThreadPool(4);
		return executorService.submit(() -> userList.stream().filter(i -> Gender.M.equals(i.getGender())).count());
	}

	static Future<Long> getMcountAsyncWithCF(List<User> userList) {
		CompletableFuture<Long> completableFuture = new CompletableFuture<>();
		new Thread(() -> {
			long count = userList.stream().filter(i -> Gender.M.equals(i.getGender())).count();
			completableFuture.complete(count);
		}).start();
		return completableFuture;
	}
	static Future<Long> getMcountAsyncWithCFWithException(List<User> userList) {
		CompletableFuture<Long> completableFuture = new CompletableFuture<>();
		new Thread(() -> {
			try {
				long count = userList.stream().filter(i -> Gender.M.equals(i.getGender())).count();
				completableFuture.complete(count);
			} catch (Exception e) {
				completableFuture.completeExceptionally(e);
			}
		}).start();
		return completableFuture;
	}

	static Future<Long> getMcountAsyncWithSupplyAsync(List<User> userList) {
		return CompletableFuture.supplyAsync(() -> userList.stream().filter(i -> Gender.M.equals(i.getGender())).count(), Executors.newFixedThreadPool(4));
	}




}
